"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

import sys
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import Permission
from django.db.models import Max, Q, DateTimeField, JSONField

from siriuso.models.postgres import CallableEncoder
from siriuso.utils import default_lingvo, get_enhavo, perms
from main.models import Uzanto
from universo_bazo.models import UniversoBazaMaks
from projektoj.models import ProjektojProjekto
from universo_bazo.models import UniversoAplikoVersio


# список изменений - change — ŝanĝi


# список listo изменений, использует абстрактный класс UniversoBazaMaks
class ChangelogListo(UniversoBazaMaks):

    # автор (пользователь, который создал сущность или для которого создана сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дата изминения
    change_dato = DateTimeField(_('Change dato'), auto_now_add=True, auto_now=False, blank=False)

    # проект
    projekto = models.ForeignKey(ProjektojProjekto, verbose_name=_('Projekto'), blank=True, null=True, default=None,
                               on_delete=models.CASCADE)

    # номер версии приложения
    versio = models.ForeignKey(UniversoAplikoVersio, verbose_name=_('Apliko Versio'), blank=True, null=True, default=None,
                               on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'changelog_listo'
        # читабельное название модели, в единственном числе
        verbose_name = _('Listo de changelog')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Listo de changelog')
        # права
        permissions = (
            ('povas_vidi_changelog_listo', _('Povas vidi listo de changelog')),
            ('povas_krei_changelog_listo', _('Povas krei listo de changelog')),
            ('povas_forigi_changelog_listo', _('Povas forigi listo de changelog')),
            ('povas_shangxi_changelog_listo', _('Povas ŝanĝi listo de changelog')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('changelog',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'changelog.povas_vidi_changelog_listo', 
                'changelog.povas_krei_changelog_listo',
                'changelog.povas_forigi_changelog_listo',
                'changelog.povas_shangxi_changelog_listo'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='changelog', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('changelog.povas_vidi_changelog_listo')
                    or user_obj.has_perm('changelog.povas_vidi_changelog_listo')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('changelog.povas_vidi_changelog_listo'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# тип изменения, использует абстрактный класс UniversoBazaMaks
class ChangelogShanghiTipo(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'changelog_shanghi_tipo'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de shanghi')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de shanghi')
        # права
        permissions = (
            ('povas_vidi_changelog_shanghi_tipo', _('Povas vidi tipoj de shanghi')),
            ('povas_krei_changelog_shanghi_tipo', _('Povas krei tipoj de shanghi')),
            ('povas_forigi_changelog_shanghi_tipo', _('Povas forigi tipoj de shanghi')),
            ('povas_shangxi_changelog_shanghi_tipo', _('Povas ŝanĝi tipoj de shanghi')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(ChangelogShanghiTipo, self).save(force_insert=force_insert, force_update=force_update,
                                               using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('changelog',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'changelog.povas_vidi_changelog_shanghi_tipo', 
                'changelog.povas_krei_changelog_shanghi_tipo',
                'changelog.povas_forigi_changelog_shanghi_tipo',
                'changelog.povas_shangxi_changelog_shanghi_tipo'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='changelog', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('changelog.povas_vidi_changelog_shanghi_tipo')
                    or user_obj.has_perm('changelog.povas_vidi_changelog_shanghi_tipo')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('changelog.povas_vidi_changelog_shanghi_tipo'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# изменения, использует абстрактный класс UniversoBazaMaks
class ChangelogShanghi(UniversoBazaMaks):

    # тип изменения, многоязычное в JSON формате
    tipo = models.ForeignKey(ChangelogShanghiTipo, verbose_name=_('Tipo'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # список изменений, многоязычное в JSON формате
    listo = models.ForeignKey(ChangelogListo, verbose_name=_('Listo'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'changelog_shanghi'
        # читабельное название модели, в единственном числе
        verbose_name = _('Shanghi')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Shanghi')
        # права
        permissions = (
            ('povas_vidi_changelog_shanghi', _('Povas vidi tipoj de shanghi')),
            ('povas_krei_changelog_shanghi', _('Povas krei tipoj de shanghi')),
            ('povas_forigi_changelog_shanghi', _('Povas forigi tipoj de shanghi')),
            ('povas_shangxi_changelog_shanghi', _('Povas ŝanĝi tipoj de shanghi')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{} - {}'.format(self.tipo, self.listo)

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(ChangelogShanghiTipo, self).save(force_insert=force_insert, force_update=force_update,
                                               using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('changelog',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'changelog.povas_vidi_changelog_shanghi', 
                'changelog.povas_krei_changelog_shanghi',
                'changelog.povas_forigi_changelog_shanghi',
                'changelog.povas_shangxi_changelog_shanghi'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='changelog', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('changelog.povas_vidi_changelog_shanghi')
                    or user_obj.has_perm('changelog.povas_vidi_changelog_shanghi')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('changelog.povas_vidi_changelog_shanghi'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


